//严格控制事件类型和传参，防止滥用造成内存浪费
interface AppEvents {
  "form:init": Record<string, unknown>;
  "form:submit": Record<string, unknown>;
}

export const useEventSystem = defineStore("event-system", () => {
  const subscribes = ref<Map<string, Function[]>>(new Map());
  const privateSubscribes = ref<Map<string, Map<string, Function[]>>>(new Map());

  function subscribe<T extends keyof AppEvents>(event: T, handler: (params: AppEvents[T]) => void) {
    if (!subscribes.value.has(event)) subscribes.value.set(event, []);
    subscribes.value.get(event)?.push(handler);
  }

  // 不传handler 取消订阅所有
  function unsubscribe<T extends keyof AppEvents>(
    event: T,
    handler?: (params: AppEvents[T]) => void
  ) {
    if (!handler) {
      subscribes.value.delete(event);
      return;
    }
    const handlers = subscribes.value.get(event);
    if (handlers) {
      const index = handlers.indexOf(handler);
      if (index > -1) handlers.splice(index, 1);
    }
  }
  function publish<T extends keyof AppEvents>(event: T, data?: AppEvents[T]) {
    const handlers = subscribes.value.get(event);
    if (handlers) {
      handlers.forEach((handle) => handle(data));
    }
  }

  function privateSubscribe<T extends keyof AppEvents>(
    id: string,
    event: T,
    handler: (params: AppEvents[T]) => void
  ) {
    if (!privateSubscribes.value.has(id)) privateSubscribes.value.set(id, new Map());
    let channel = privateSubscribes.value.get(id)!;
    if (!channel.has(event)) channel.set(event, []);
    channel.get(event)?.push(handler);
  }

  function privateUnsubscribe<T extends keyof AppEvents>(
    id: string,
    event: T,
    handler?: (params: AppEvents[T]) => void
  ) {
    if (!privateSubscribes.value.has(id)) return;
    let channel = privateSubscribes.value.get(id)!;
    if (!handler) channel.delete(event);
    else {
      let handlers = channel.get(event);
      if (handlers) {
        let index = handlers.indexOf(handler);
        if (-1 !== index) handlers.splice(index, 1);
      }
    }
  }

  function privatePublish<T extends keyof AppEvents>(id: string, event: T, data: AppEvents[T]) {
    if (!privateSubscribes.value.has(id)) return;
    let handlers = privateSubscribes.value.get(id)?.get(event);
    if (handlers) handlers.forEach((handler) => handler(data));
  }

  return {
    privatePublish,
    privateSubscribe,
    privateUnsubscribe,
    subscribe,
    unsubscribe,
    publish,
    subscribes,
    privateSubscribes,
    on: subscribe,
    emit: publish,
  };
});
